package view.panel;

import dao.CategoryDAO;
import dao.ShopDAO;
import tool.DisableEditTableModel;

import javax.swing.*;

import bean.Commodity;
import bean.Category;

import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Hashtable;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.Vector;

public class ShopPanel extends JPanel {
    private static final long serialVersionUID = -972682960465192193L;
    private CategoryDAO categoryDAO;
    private ShopDAO shopDAO;
    private Dimension dimension;
    private Hashtable<Integer, String> commodityTypeData;
    private Set<Map.Entry<Integer, String>> commodityTypeDataEntrySet;
    private JPanel northPanel;
    private JTextField queryIdTextField;
    private JTextField queryKeywordTextField;
    private JComboBox<String> queryCategoriesComboBox;
    private DefaultComboBoxModel<String> queryComboBoxModel;
    private JButton queryButton;
    private JScrollPane scrollPane;
    private JTable table;
    private DisableEditTableModel tableModel;
    private Vector<String> columnNames;
    private JPanel southPanel;
    private int quantity = 0;
    private JTextField purchaseQuantityTextField;
    private JButton addCommodityToCartButton;

    public ShopPanel(Connection conn) throws SQLException {
        super(new BorderLayout());
        shopDAO = new ShopDAO(conn);
        categoryDAO = new CategoryDAO(conn);
        setName("购物");
        dimension = new Dimension(83, 22);
        comboBoxItems();
        northPanel = new JPanel();
        add(northPanel, BorderLayout.NORTH);
        northPanel.add(new JLabel("商品编号"));
        queryIdTextField = new JTextField();
        queryIdTextField.setPreferredSize(dimension);
        queryIdTextField.addFocusListener(new FocusListener() {
            @Override
            public void focusGained(FocusEvent focusEvent) {}

            @Override
            public void focusLost(FocusEvent focusEvent) {
                JTextField source = (JTextField) focusEvent.getComponent();
                String commodityId = source.getText();
                if (Objects.nonNull(commodityId) && commodityId.length() > 0) {
                    queryKeywordTextField.setText(null);
                    queryCategoriesComboBox.setSelectedIndex(0);
                }
            }
        });
        northPanel.add(queryIdTextField);
        northPanel.add(new JLabel("商品关键字"));
        queryKeywordTextField = new JTextField();
        queryKeywordTextField.setPreferredSize(dimension);
        queryKeywordTextField.addFocusListener(new FocusListener() {
            @Override
            public void focusGained(FocusEvent focusEvent) {}

            @Override
            public void focusLost(FocusEvent focusEvent) {
                JTextField source = (JTextField) focusEvent.getComponent();
                String commodityKeyword = source.getText();
                if (Objects.nonNull(commodityKeyword) && commodityKeyword.length() > 0) {
                    queryIdTextField.setText(null);
                }
            }
        });
        northPanel.add(queryKeywordTextField);
        northPanel.add(new JLabel("商品类别"));
        queryCategoriesComboBox = new JComboBox<>();
        queryCategoriesComboBox.setPreferredSize(dimension);
        queryCategoriesComboBox.addItemListener(itemEvent -> {
            if (itemEvent.getStateChange() == ItemEvent.SELECTED) {
                queryIdTextField.setText(null);
            }
        });
        northPanel.add(queryCategoriesComboBox);
        queryButton = new JButton("查询商品");
        queryButton.addActionListener(actionEvent -> {
            String queryId = queryIdTextField.getText();
            try {
                int categoryId = 0;
                // 通过商品编号查询
                if (Objects.nonNull(queryId) && queryId.length() > 0) {
                    int commodityId = Integer.parseInt(queryId);
                    tableModel.setDataVector(getRowsData(commodityId), columnNames());
                } else {
                    // 通过商品关键字及所属商品类别查询
                    String keyword = queryKeywordTextField.getText();
                    String categoryName = (String) queryCategoriesComboBox.getSelectedItem();
                    for (Map.Entry<Integer, String> entry : commodityTypeDataEntrySet) {
                        if (entry.getValue().equals(categoryName)) {
                            categoryId = entry.getKey();
                            break;
                        }
                    }
                    tableModel.setDataVector(getRowsData(keyword, categoryId), columnNames());
                }
                if (categoryId == 0) {
                    comboBoxItems();
                    addItemsToComboBoxes();
                }
            } catch (NumberFormatException e) {
                JOptionPane.showMessageDialog(null, "商品编号不是纯数字");
                queryIdTextField.requestFocusInWindow();
                queryIdTextField.selectAll();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        });
        northPanel.add(queryButton);
        scrollPane = new JScrollPane();
        table = new JTable();
        tableModel = new DisableEditTableModel();
        tableModel.setDataVector(getRowsData(null, 0), columnNames());
        table.setModel(tableModel);
        scrollPane.setViewportView(table);
        add(scrollPane, BorderLayout.CENTER);
        southPanel = new JPanel();
        add(southPanel, BorderLayout.SOUTH);
        southPanel.add(new JLabel("购买商品数量"));
        purchaseQuantityTextField = new JTextField();
        purchaseQuantityTextField.setPreferredSize(dimension);
        southPanel.add(purchaseQuantityTextField);
        addCommodityToCartButton = new JButton("添加商品至购物车");
        addCommodityToCartButton.addActionListener(actionEvent -> {
            if (table.getSelectedRows().length != 1) {
                JOptionPane.showMessageDialog(null, "必须从商品购物表中选择唯一一种商品");
            } else {
                int rowIndex = table.getSelectedRow();
                int commodityId = (int) tableModel.getValueAt(rowIndex, 0);
                try {
                    int purchaseQuantity = Integer.parseInt(purchaseQuantityTextField.getText());
                    Commodity commodity = shopDAO.selectByCommodityId(commodityId);
                    quantity = commodity.getQuantity();
                    if (purchaseQuantity <= 0) {
                        JOptionPane.showMessageDialog(null, "购买商品数量必须大于0");
                    } if (purchaseQuantity > quantity) {
                        JOptionPane.showMessageDialog(null, "购买商品数量不能大于商品现有数量");
                    } else {
                        // 购买商品数量大于0且小于商品现有数量
                        JPanel cardPanel = (JPanel) getParent();
                        BillPanel billPanel = (BillPanel) cardPanel.getComponent(0);
                        JScrollPane scrollPane = (JScrollPane) billPanel.getComponent(0);
                        JTable table = (JTable) scrollPane.getViewport().getView();
                        DisableEditTableModel tableModel = (DisableEditTableModel) table.getModel();
                        int rowCount = tableModel.getRowCount();
                        int row = 0;
                        // 如果购物车为空或者购物车存在商品
                        while (rowCount == 0 || row < rowCount) {
                            // 如果是，则更改商品编号所在表格行的商品数量和商品总价
                            if (rowCount > 0 && commodityId == (int) tableModel.getValueAt(row, 0)) {
                                int purchasedQuantity = (int) tableModel.getValueAt(row, 3) + purchaseQuantity;
                                BigDecimal purchasedTotalPrice = (BigDecimal) tableModel.getValueAt(row, 4);
                                BigDecimal purchaseTotalPrice = new BigDecimal(purchaseQuantity).multiply(commodity.getSalePrice());
                                purchasedTotalPrice = purchasedTotalPrice.add(purchaseTotalPrice);
                                BigDecimal singleAveragePrice = purchasedTotalPrice.divide(new BigDecimal(purchasedQuantity), 2, RoundingMode.HALF_UP);
                                tableModel.setValueAt(singleAveragePrice, row, 2);
                                tableModel.setValueAt(purchasedQuantity, row, 3);
                                tableModel.setValueAt(purchasedTotalPrice, row, 4);
                                break;
                            } else if (rowCount == 0 || row == rowCount - 1) {
                                BigDecimal salePrice = commodity.getSalePrice();
                                BigDecimal purchaseTotalPrice = new BigDecimal(purchaseQuantity).multiply(salePrice);
                                Object[] rowData = new Object[5];
                                rowData[0] = commodityId;
                                rowData[1] = commodity.getCommodityName();
                                rowData[2] = salePrice;
                                rowData[3] = purchaseQuantity;
                                rowData[4] = purchaseTotalPrice;
                                tableModel.addRow(rowData);
                                break;
                            }
                            row++;
                        }
                        int quantity = commodity.getQuantity() - purchaseQuantity;
                        this.tableModel.setValueAt(quantity, rowIndex, 4);
                        commodity.setQuantity(quantity);
                        shopDAO.update(commodity);
                        purchaseQuantityTextField.setText(null);
                    }
                } catch (NumberFormatException e) {
                    JOptionPane.showMessageDialog(null, "购买商品数量不是纯数字");
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        });
        southPanel.add(addCommodityToCartButton);
        addItemsToComboBoxes();
    }

    private Vector<String> comboBoxItems() throws SQLException {
        commodityTypeData = new Hashtable<>();
        Vector<Category> categories = categoryDAO.selectAll();
        for (Category category : categories) {
            int categoryId = category.getCategoryId();
            String categoryName = category.getCategoryName();
            commodityTypeData.put(categoryId, categoryName);
        }
        Vector<String> items = new Vector<>();
        commodityTypeDataEntrySet = commodityTypeData.entrySet();
        for (Map.Entry<Integer, String> entry : commodityTypeDataEntrySet) {
            String categoryName = entry.getValue();
            items.addElement(categoryName);
        }
        return items;
    }

    private void addItemsToComboBoxes() throws SQLException {
        Vector<String> items = comboBoxItems();
        items.add(0, "未指定");
        queryComboBoxModel = new DefaultComboBoxModel<>(items);
        queryCategoriesComboBox.setModel(queryComboBoxModel);
    }

    private Vector<String> columnNames() {
        columnNames = new Vector<>();
        columnNames.addElement("商品编号");
        columnNames.addElement("商品名称");
        columnNames.addElement("商品类别");
        columnNames.addElement("商品价格");
        columnNames.addElement("商品数量");
        return columnNames;
    }

    private Vector<Vector<Object>> getRowsData(int commodityId) throws SQLException {
        Commodity commodity = shopDAO.selectByCommodityId(commodityId);
        Vector<Vector<Object>> rowsData = new Vector<>();
        if (Objects.nonNull(commodity)) {
            addRowToRows(rowsData, commodity);
        }
        return rowsData;
    }

    private Vector<Vector<Object>> getRowsData(String keyword, int categoryId) throws SQLException {
        Vector<Commodity> commodities = shopDAO.selectByKeyword(keyword, categoryId);
        Vector<Vector<Object>> rowsData = new Vector<>();
        for (Commodity commodity : commodities) {
            addRowToRows(rowsData, commodity);
        }
        return rowsData;
    }

    private void addRowToRows(Vector<Vector<Object>> rowsData, Commodity commodity) {
        Vector<Object> rowData = new Vector<>();
        rowData.addElement(commodity.getCommodityId());
        rowData.addElement(commodity.getCommodityName());
        rowData.addElement(commodity.getCategoryName());
        rowData.addElement(commodity.getSalePrice());
        rowData.addElement(commodity.getQuantity());
        rowsData.addElement(rowData);
    }
}
